package cn.wen.forum.common.util;

import cn.wen.forum.ForumApplication;
import cn.wen.forum.common.enums.ResultCode;
import cn.wen.forum.common.exception.ServiceException;
import cn.wen.forum.config.InitSysParams;
import cn.wen.forum.constants.ForumConstant;
import cn.wen.forum.mapper.UserMapper;
import cn.wen.forum.pojo.entity.User;
import com.alibaba.fastjson.JSONObject;

import java.util.*;

/**
 * @ClassName LevelUtils
 * @Author By wen
 * @Description 等级处理工具类
 * @Date 2023/8/14 14:20
 * @Version 1.0
 */
public class LevelUtils {

    private static final RedisUtils redisUtils = ForumApplication.ac.getBean(RedisUtils.class);

    private static final UserMapper userMapper = ForumApplication.ac.getBean(UserMapper.class);

    /**
     * 根据等级和经验值 判断 是否升级,是则更新
     * @param level 当前等级
     * @param empiricalValue 当前增长后的经验值
     * @param UID 用户UID
     * @return
     */
    public static void isUpgradeLevel(Integer level, Integer empiricalValue,Long UID) throws Exception {
        Map<String, String> map = InitSysParams.getLevelCacheMap();
        // 当前等级为最高时，则不用进行后续逻辑
        if(level == map.size()){
            return;
        }
        // 如果当前经验值已经大于当前等级的下一等级所需要经验值的阈值，则说明用户等级需要升级了
        if(empiricalValue > Integer.parseInt(map.get((level + 1) + ""))){
            // 如果经验值大于当前等级的两个等级段的经验值，说明用户非法升级了
            if(empiricalValue > Integer.parseInt(map.get((level + 2) + ""))) {
                throw new ServiceException(ResultCode.USER_LEVEL_ILLEGAL);
            }
            // 更新等级信息
            User user = new User();
            user.setId(UID);
            user.setLevel(level + 1);
            user.setEmpiricalValue(empiricalValue);
            userMapper.updateById(user);
            // 刷新缓存的操作用户user缓存信息
            User cacheUserInfo = redisUtils.getCacheObject(ForumConstant.USER_INFO + UID);
            cacheUserInfo.setLevel(level + 1);
            redisUtils.setCacheObject(ForumConstant.USER_INFO + UID,cacheUserInfo);
        }
    }

    /**
     * 增加当前用户的经验值
     * @param UID
     * @param addType 增加经验值类型
     * @param isFirstLogin 是否今日日首次登陆
     */
    public static boolean updateEmpiricalValue(Long UID,String addType,boolean isFirstLogin) throws Exception{
        User userInfo = null;
        Object userObj = redisUtils.getCacheObject(ForumConstant.USER_INFO + UID);
        if(StringUtils.isNull(userObj)) {
            User userEntity = userMapper.selectById(UID);
            userInfo = new User();
            userInfo.setId(userEntity.getId());
            userInfo.setLevel(userEntity.getLevel());
            userInfo.setAttentionNum(userEntity.getAttentionNum());
            userInfo.setPostNum(userEntity.getPostNum());
            userInfo.setApprovalNum(userEntity.getApprovalNum());
            userInfo.setEmpiricalValue(userEntity.getEmpiricalValue());

            userInfo.setDayReviewNum(0);
            userInfo.setDayPushPostNum(0);
            userInfo.setDayApprovalNum(0);
            userInfo.setLoginTimeStr(DateUtils.parseToDateStr(new Date()));
        } else {
            userInfo = JSONObject.parseObject(userObj.toString(), User.class);
        }
        if(isFirstLogin){
            // 每日首次登陆重置每天评论发布点赞信息
            userInfo.setDayReviewNum(0);
            userInfo.setDayPushPostNum(0);
            userInfo.setDayApprovalNum(0);
            userInfo.setLoginTimeStr(DateUtils.parseToDateStr(new Date()));
        }
        // 增加经验值逻辑
        switch (addType) {
            // 每日登录
            case ForumConstant.ADD_TYPE_LOGIN:
                userInfo.setEmpiricalValue(userInfo.getEmpiricalValue() + ForumConstant.LOGIN_EMPIRICAL);
                break;
            // 评论
            case ForumConstant.ADD_TYPE_REVIEW:
                // 每日最多5条评论增长经验
                if(userInfo.getDayReviewNum() < 5) {
                    userInfo.setEmpiricalValue(userInfo.getEmpiricalValue() + ForumConstant.REVIEW_EMPIRICAL);
                    userInfo.setDayReviewNum(userInfo.getDayReviewNum() + 1);
                } else{
                    return false;
                }
                break;
            // 发布
            case ForumConstant.ADD_TYPE_PUBLISH:
                // 每日最多5条发布增长经验
                if(userInfo.getDayPushPostNum() < 6) {
                    userInfo.setEmpiricalValue(userInfo.getEmpiricalValue() + ForumConstant.PUBLISH_EMPIRICAL);
                    userInfo.setDayPushPostNum(userInfo.getDayPushPostNum() + 1);
                } else{
                    return false;
                }
                break;
            // 被回复
            case ForumConstant.ADD_TYPE_REVIEW_Y:
                break;
            // 被点赞
            case ForumConstant.ADD_TYPE_APPROVAL_Y:
                break;
            default:
                break;
        }
        redisUtils.setCacheObject(ForumConstant.USER_INFO + userInfo.getId(),userInfo);

        // 设置每日活跃用户缓存
        Set<String> activeUserSet = redisUtils.getCacheSet(ForumConstant.USER_ACTIVE_INFO);
        if(StringUtils.isNull(activeUserSet)) {
            activeUserSet = new HashSet<String>();
        }
        activeUserSet.add(UID+"");
        redisUtils.setCacheSet(ForumConstant.USER_ACTIVE_INFO,activeUserSet);

        // 是否要提升等级
        isUpgradeLevel(userInfo.getLevel(),userInfo.getEmpiricalValue(),userInfo.getId());
        return true;
    }

    /**
     * 根据等级获取头衔
     * @param level
     * @return
     */
    public static String levelToLevelName(Integer level) {
        return "LV"+level + " " + InitSysParams.getSysParamByID(ForumConstant.LV + level);
    }
}
